package com.epoch.base.model;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.epoch.base.shiro.ShiroKit;
import com.epoch.base.util.DateUtils;
import com.epoch.base.util.UuidUtil;
import com.jfinal.kit.Kv;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.SqlPara;
import com.jfinal.plugin.activerecord.Table;
import com.jfinal.plugin.activerecord.TableMapping;

@SuppressWarnings("rawtypes")
public class BaseModel<M extends Model> extends Model<M>{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
    public static final String CREATE_BY = "CREATE_BY";
    public static final String CREATE_DATE = "CREATE_DATE";
    public static final String CREATE_DEPT = "CREATE_DEPT";
    public static final String UPDATE_DATE = "UPDATE_DATE";
    public static final String UPDATE_BY = "UPDATE_BY";
	
	@Override
	public Integer getInt(String attr) {
		Object obj = get(attr);
		if (obj == null) {
			return null;
		} else if (obj instanceof Integer) {
			return (Integer) obj;
		} else if (obj instanceof BigDecimal) {
			return ((BigDecimal) obj).intValue();
		} else if (obj instanceof String) {
			try {
				return Integer.parseInt((String) obj);
			} catch (Exception e) {
				throw new RuntimeException("String can not cast to Integer : " + attr.toString());
			}
		} else {
			try {
				return Integer.parseInt(obj.toString());
			} catch (Exception e) {
				throw new RuntimeException("Object can not cast to Integer : " + attr.toString());
			}
		}
	}
	
	public Page<M> paginate(Kv params, String select, String sqlPara, Object... paras) {
		return paginate(params.getInt("pageNumber"), params.getInt("pageSize"), select, sqlPara, paras);
	}
	
	public Table getTable() {
		return TableMapping.me().getTable(getClass());
	}
	
	public M selectOne(SqlPara sqlPara) {
		List<M> list = this.find(sqlPara);
		return list.get(0);
	}
	
    private Class<? extends Model> getUsefulClass() {
        Class c = getClass();
        return c.getName().indexOf("EnhancerByCGLIB") == -1 ? c : c
                .getSuperclass(); // com.demo.blog.Blog$$EnhancerByCGLIB$$69a17158
    }

	@Override
	public boolean save() {
		Table table = TableMapping.me().getTable(getUsefulClass());
		Date now = DateUtils.getCurrentDate();
        String userId = null;
        String userDeptId = null;
        try {
            userId = ShiroKit.getUserId();
            userDeptId = ShiroKit.getUserDeptId();
        } catch (Exception e) {
            e.printStackTrace();
        }
        Map<String, Class<?>> columnAll = table.getColumnTypeMap();
        String[] tar = table.getPrimaryKey();
        if(this.get(tar[0]) == null) {
        	this.set(tar[0], UuidUtil.getUUID());
        }
        if(this.get(tar[0]) != null && this.get(tar[0]).toString().startsWith("_auto") ) {
        	this.set(tar[0], UuidUtil.getUUID());
        }
        if (columnAll.containsKey("CREATE_BY") && this.get("CREATE_BY") == null) {
            this.set("CREATE_BY", userId);
        }
        if (columnAll.containsKey("CREATE_DATE") && this.get("CREATE_DATE") == null) {
            this.set("CREATE_DATE", now);
        }
        if (columnAll.containsKey("CREATE_DEPT") && this.get("CREATE_DEPT") == null) {
            this.set("CREATE_DEPT", userDeptId);
        }
        if (columnAll.containsKey(UPDATE_BY) && this.get(UPDATE_BY) == null) {
            this.set(UPDATE_BY, userId);
        }
        if (columnAll.containsKey(UPDATE_DATE) && this.get(UPDATE_DATE) == null) {
            this.set(UPDATE_DATE, now);
        }
        boolean result = super.save();
        return result;
	}
	
	public boolean saveOrUpdate() {
        Table table = TableMapping.me().getTable(getUsefulClass());
        String[] primaryKay = table.getPrimaryKey();
        String primary = primaryKay[0];
        if (null == this.get(primary)|| this.get(primary).toString().startsWith("_auto")) {
            return this.save();
        } else {
            return this.update();
        }
    }

	@Override
	public boolean update() {
		Table table = TableMapping.me().getTable(getUsefulClass());
		//自动添加创建时间和更新时间
        Date now = DateUtils.getCurrentDate();
        String userId = null;
        try {
            userId = ShiroKit.getUserId();
        } catch (Exception e) {
            e.printStackTrace();
        }
        Map<String, Class<?>> columnAll = table.getColumnTypeMap();
        if (columnAll.containsKey(UPDATE_BY)) {
            this.set(UPDATE_BY, userId);
        }
        if (columnAll.containsKey("UPDATE_DATE")) {
            this.set("UPDATE_DATE", now);
        }
        boolean result = super.update();
        return result;
	}
	
    public Page<M> paginate(SqlPara sqlPara,Kv params) {
        return super.paginate(params.getInt("pageNumber"), params.getInt("pageSize"), sqlPara);
    }
	
    public String getMyString(String attr) {
        if (attr == null)
            return null;
        if (get(attr) == null)
            return null;

        Object obj = get(attr);
        String result = null;

        if (obj instanceof BigDecimal) {
            BigDecimal val = (BigDecimal) obj;
            result = val.toString();
        } else if (obj instanceof Integer) {
        	Integer val = (Integer) obj;
            result = val.toString();
        } else if (obj instanceof String) {
            String val = (String) obj;
            result = val;
        } else if (obj instanceof Long) {
            result = obj.toString();
        } else if (obj instanceof Float) {
            result = ((Float) obj).toString();
        }

        return result;
    }
    
    public void copyProperties(BaseModel toObj) {
        Set<Map.Entry<String, Object>> entrySet = this._getAttrsEntrySet();
        for (Map.Entry<String, Object> entry : entrySet) {
            toObj.put(entry.getKey(), entry.getValue());
        }
    }
	
	
}
